#include <windows.h>

///////////////////////////////////////////////////////////////////////////////
/// CUST HEADER
#include "qComm.h"
#include "qList.h"


void qlsti_dumper (void* trg)
{
	QLST_LST_TYPE*	lst = NULL;
	QLST_ITM_TYPE*	itm = NULL;
	int				ind = 0x0;

	if (trg == NULL) return;
	lst = (QLST_LST_TYPE*) trg;
	itm = lst->head;

	printf ("\n");
	printf ("=================================================================\n");
	printf ("[QLST][List][0x%08x]\n", lst);
	printf ("[QLST][Head][0x%08x]\n", lst->head);
	printf ("[QLST][Tail][0x%08x]\n", lst->tail);

	while (itm != NULL) {
		printf ("[QLST][item%2d][0x%08x]\n", ind, itm);
		itm = itm->nxt;
		ind++;
	};
	
	return;
}

void* qlst_create_lst (void)
{
	QLST_LST_TYPE*	lst = NULL;
	
	QM_ALLOC_STRUCT (QLST_LST_TYPE, lst);
	lst->head = NULL;
	lst->tail = NULL;
	
	return lst; 
}

void qlst_delete_lst (void* contn)
{
	QLST_LST_TYPE*	lst = (QLST_LST_TYPE*)contn;

    if ((lst->head != NULL) ||
        (lst->tail != NULL) )
    {
        /// QERR ("memory leak issue.!!)
        printf ("memory leak.!!");
    }
    
    QM_FREE (lst);
    return;
}

void* qlst_new_itm (void)
{
    QLST_ITM_TYPE* itm;

    QM_ALLOC_STRUCT(QLST_ITM_TYPE, itm);
    return itm;
}

void qlst_free_itm (void* one)
{
    QLST_ITM_TYPE* itm = (QLST_ITM_TYPE*)one;
    if (itm != NULL) {
        QM_FREE(itm);
        one = NULL;
    }
    
    return;
}

void qlst_put (void* aitm, void* into_lst)
{
    QLST_LST_TYPE* lst = (QLST_LST_TYPE*) into_lst;
    QLST_ITM_TYPE* itm = (QLST_ITM_TYPE*) aitm;
    
    if (lst == NULL)
        return;

    if (itm == NULL)
        return;

    /// case: head(NULL)
    ///       .nxt
    if (lst->head == NULL) { 
        /// 1st itm
        lst->head = itm;
        lst->head->nxt = NULL;
    }
    /// case: head(NULL)
    ///       .nxt-> tail(NULL)
    else if (lst->tail == NULL) { 
        /// 2nd itm
        lst->head->nxt = itm;
        lst->tail = itm;
        lst->tail->nxt = NULL;
    }
    /// case: head
    ///       .nxt-> ... -> tail
    ///                     .nxt -> NULL
    else {
        lst->tail->nxt = itm;
        lst->tail = itm;
        lst->tail->nxt = NULL;
    }
    
    return;
}

void qlst_pullup (void** itm, void* frm_lst)
{
    QLST_LST_TYPE* lst = (QLST_LST_TYPE*) frm_lst;
    QLST_ITM_TYPE* one = NULL;

    /// case: head(NULL)
    ///       .nxt
    if ((lst == NULL) ||
		(lst->head == NULL)) {
        *itm = 0x0;
	}
    /// case: head
    ///       .nxt->tail(NULL)
    else if (lst->tail == NULL) {
        one = lst->head;
        lst->head = NULL;
		*itm = (void*) one;
    }
    else {
        /// case: head
        ///       .nxt->tail
        ///             .nxt->NULL
		if (lst->head->nxt == lst->tail) {
            lst->tail = NULL;
		}

		/// case: head
		///       .nxt-> ...  -> tail
		///                     .nxt->NULL
		one = lst->head;
		lst->head = lst->head->nxt;
		*itm = (void*) one;
    }

	*itm = (void*) one;
	return;
}


void qlst_unit_test (void)
{

	static QLST_LST_TYPE* utlst = (QLST_LST_TYPE*) qlst_create_lst();
	static QLST_ITM_TYPE* utimt = NULL;


	for (int i=0; i<10; i++) {
		utimt = (QLST_ITM_TYPE*)qlst_new_itm();
		qlst_put((void*) utimt, (void*) utlst);
	}

	qlsti_dumper((void*) utlst);

	utimt = NULL;
	for (;;) {
		qlst_pullup ((void**)&utimt, (void*) utlst);

		if (utimt == NULL) break;
		
		qlsti_dumper ((void*) utlst);
		qlst_free_itm ((void*) utimt);
	};

	qlst_delete_lst((void*) utlst);

	return;
}
